using System;
using System.ComponentModel.Design;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using EnvDTE;
using System.Globalization;
using System.Configuration;
using System.ComponentModel;
using Microsoft.Practices.Common;
using Microsoft.Practices.RecipeFramework.Library;
using Microsoft.Practices.RecipeFramework.Extensions.Converters;


namespace Microsoft.Practices.RepositoryFactory.Converters
{
    public class ConnectionStringConverter : StringConverter, IAttributesConfigurable
    {
        // Fields
        private string configurationArgument;
        public const string ConfigurationItemArgument = "ConfigurationItemArgument";

        // Methods
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType != typeof(string))
            {
                return (destinationType == typeof(ConnectionStringSettings));
            }
            return true;
        }

        private int CompareConnectionStringSettings(ConnectionStringSettings x, ConnectionStringSettings y)
        {
            return string.Compare(x.Name, y.Name, StringComparison.InvariantCulture);
        }

        public void Configure(StringDictionary attributes)
        {
            if (attributes.ContainsKey("ConfigurationItemArgument"))
            {
                this.configurationArgument = attributes["ConfigurationItemArgument"];
            }
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string)
            {
                ConnectionStringsSection section = ConnectionSettingsInfo.GetSection((DTE)context.GetService(typeof(DTE)));
                if (section != null)
                {
                    return section.ConnectionStrings[(string)value];
                }
            }
            return null;
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType != typeof(string))
            {
                return base.ConvertTo(context, culture, value, destinationType);
            }
            if (value is ConnectionStringSettings)
            {
                return ((ConnectionStringSettings)value).Name;
            }
            return value.ToString();
        }

        public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            ConnectionStringsSection section = null;
            if (string.IsNullOrEmpty(this.configurationArgument))
            {
                DTE vs = (DTE) context.GetService(typeof(DTE));
                if (vs == null)
                {
                    return new TypeConverter.StandardValuesCollection(null);
                }
                if (DteHelper.GetSelectedProject(vs) == null)
                {
                    return new TypeConverter.StandardValuesCollection(null);
                }
                section = ConnectionSettingsInfo.GetSection(vs);
            }
            else
            {
                IDictionaryService service = (IDictionaryService) context.GetService(typeof(IDictionaryService));
                ProjectItem item = service.GetValue(this.configurationArgument) as ProjectItem;
                if (item != null)
                {
                    section = ConnectionSettingsInfo.GetSection(item.get_FileNames(1));
                }
            }
            if (section == null)
            {
                return new TypeConverter.StandardValuesCollection(null);
            }
            List<ConnectionStringSettings> list = new List<ConnectionStringSettings>(section.ConnectionStrings.Count);
            IEnumerator enumerator = section.ConnectionStrings.GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    ConnectionStringSettings settings = (ConnectionStringSettings) enumerator.Current;
                    list.Add(settings);
                }
            }
            finally
            {
                IDisposable disposable = enumerator as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
            }
            
            //list.Sort(new Comparison<ConnectionStringSettings>(this, this.CompareConnectionStringSettings));

            list.Sort(new Comparison<ConnectionStringSettings>(this.CompareConnectionStringSettings));

            return new TypeConverter.StandardValuesCollection(list);
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true;
        }

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override bool IsValid(ITypeDescriptorContext context, object value)
        {
            if (value is ConnectionStringSettings)
            {
                return true;
            }
            if (!(value is string))
            {
                return false;
            }
            ConnectionStringsSection section = (ConnectionStringsSection) ConnectionSettingsInfo.GetSection((DTE)context.GetService(typeof(DTE)));
            if (section == null)
            {
                return false;
            }
            return (section.ConnectionStrings[(string)value] != null);
        }
    }


}
